package com.yakami.ocean;

import android.content.SharedPreferences;

import com.yakami.ocean.bean.Classify;
import com.yakami.ocean.bean.ClassifyListContainer;
import com.yakami.ocean.bean.HomeData;
import com.yakami.ocean.bean.ListContainer;
import com.yakami.ocean.bean.News;
import com.yakami.ocean.bean.PopularListContainer;
import com.yakami.ocean.bean.StrResult;
import com.yakami.ocean.bean.TestPaper;
import com.yakami.ocean.bean.TestPaperProfile;
import com.yakami.ocean.bean.TestRecord;
import com.yakami.ocean.bean.UserDetailInfo;
import com.yakami.ocean.bean.UserInfo;
import com.yakami.ocean.bean.UserLoginInfo;
import com.yakami.ocean.bean.BoolResult;
import com.yakami.ocean.model.SharePreferenceManager;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;
import retrofit2.http.Streaming;
import rx.Observable;


public class ServerAPI {

//    public final static String host = "http://192.168.137.1";
    public final static String host = "http://112.74.204.89";
    private static OceanAPI mOceanAPI;
    private static String mCookies;
    private static String mSessionCookies;

    public static OceanAPI getOceanAPI() {
        if (mOceanAPI == null) {
            OkHttpClient httpClient = new OkHttpClient.Builder()
                    .addInterceptor((Interceptor.Chain chain) -> {
                                Request original = chain.request();
                                switch (original.url().url().getPath()) {
                                    case "/User/Login":
                                        Response response = chain.proceed(chain.request());
                                        setCookies(response.header("Set-Cookie"));
                                        return response;
                                    case "/User/GetValidateCode":
                                        Response codeResponse = chain.proceed(chain.request());
                                        mSessionCookies = codeResponse.header("Set-Cookie");
                                        return codeResponse;
                                    case "/User/SignUp":
                                        Request.Builder signUpRequestBuilder = original.newBuilder()
                                                .header("Cookie", mSessionCookies == null ? "" : mSessionCookies)
                                                .method(original.method(), original.body());
                                        Request signUpRequest = signUpRequestBuilder.build();
                                        return chain.proceed(signUpRequest);
                                    default:
                                        Request.Builder requestBuilder = original.newBuilder()
                                                .header("Cookie", mCookies == null ? getCookies() : mCookies)
                                                .method(original.method(), original.body());
                                        Request request = requestBuilder.build();
                                        return chain.proceed(request);
                                }
//                                if (original.url().url().getPath().equals("/User/Login")) {
//                                    Response response = chain.proceed(chain.request());
//                                    setCookies(response.header("Set-Cookie"));
//                                    return response;
//                                } else {
//                                    Request.Builder requestBuilder = original.newBuilder()
//                                            .header("Cookie", mCookies == null ? getCookies() : mCookies)
//                                            .method(original.method(), original.body());
//                                    Request request = requestBuilder.build();
//                                    return chain.proceed(request);
//                                }
                            }
                    ).build();

            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(ServerAPI.host)
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(httpClient)
                    .build();

            mOceanAPI = retrofit.create(ServerAPI.OceanAPI.class);
        }
        return mOceanAPI;
    }

    public static void setCookies(String cookies) {
        mCookies = cookies;
        SharedPreferences.Editor editor = SharePreferenceManager.getUser().edit();
        editor.putString(SharePreferenceManager.User.KEY_COOKIES, cookies);
        editor.apply();
        clearCookies();
    }


    public static String getCookies() {
        if (mCookies == null) {
            SharedPreferences preferences = SharePreferenceManager.getUser();
            return mCookies = preferences.getString(SharePreferenceManager.User.KEY_COOKIES, "");
        }
        return mCookies;
    }

    public static void clearCookies() {
        mCookies = null;
    }

    public static String getPreviewImgUrl(String url) {
        try {
            return ServerAPI.host + "/Home/GetArticleImg" + "?url=" + URLEncoder.encode(url, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    public static String getValidateCode() {
        return ServerAPI.host + "/User/GetValidateCode";
    }

    public static String getUploadsUrl(String url) {
        return ServerAPI.host + "/Uploads/" + url;
    }

    public interface OceanAPI {

        @GET("/Home/HomeDataAPI")
        Observable<HomeData> getHomeData();

        @GET("/Home/HomeDataAPIByType")
        Observable<ListContainer<News>> getHomeDataByType(@Query("type") String type);

        @GET("/Home/GetArticleImg")
        Observable<Byte[]> getArticleImg(@Query("url") String url);

        @GET("/Home/GetTypeTree")
        Observable<ListContainer<Classify>> getTypeTree();

        @GET("/Home/ClassifyPostListAPI")
        Observable<ClassifyListContainer<News>> getClassifyPostList(@Query("firstClassify") String firstClassify,
                                                                    @Query("secondClassify") String secondClassify);

        @GET("/Home/PopularPostListAPI")
        Observable<PopularListContainer<News>> getPopularPostList();

        @GET("/Test/GetTestPaperList")
        Observable<ListContainer<TestPaperProfile>> getTestPaperList();

        @GET("/Test/GetTest")
        Observable<TestPaper> getTestPaper(@Query("id") int id);

        @GET("/Home/GetRawArticle")
        Observable<ResponseBody> getRawArticle(@Query("id") int id);

        @GET("/Home/AppSearchAPI")
        Observable<ListContainer<News>> search(@Query("searchStr") String searchStr);

        @POST("/User/Login")
        Observable<UserLoginInfo> login(@Query("userName") String name,
                                        @Query("password") String password,
                                        @Query("rememberMe") boolean rememberMe);

        @GET("/User/GetUserInfo")
        Observable<UserInfo> getUserInfo();

        @GET("/User/OutLogin")
        Observable<StrResult> outLogin();

        @POST("/User/SignUp")
        Observable<StrResult> signUp(@Query("name") String name,
                                     @Query("pwd") String pwd,
                                     @Query("rePwd") String rePwd,
                                     @Query("email") String email,
                                     @Query("code") String code);

        @GET("/User/GetValidateCode")
        @Streaming
        Observable<ResponseBody> getValidateCode();

        @GET("/user/GetUserDetailedInfo")
        Observable<UserDetailInfo> getUserDetailedInfo(@Query("type") String type);

        @GET("/home/ThumbUp")
        Observable<BoolResult> thumbUp(@Query("articleId") int id);

        @GET("/home/CheckCollection")
        Observable<BoolResult> isCollected(@Query("articleId") int id);

        @GET("/home/collectArticle")
        Observable<StrResult> collectArticle(@Query("articleId") int id);

        @GET("/home/CancelCollection")
        Observable<StrResult> cancelCollection(@Query("articleId") int id);

        @GET("/user/CollectionListAPI")
        Observable<PopularListContainer<News>> getCollectionList();

        @GET("/user/GetUserDetailedInfo?type=%E6%B5%8B%E8%AF%95%E8%AE%B0%E5%BD%95")
        Observable<ListContainer<TestRecord>> getTestRecord();

        @POST("/test/SetTestAccord")
        Observable<StrResult> setTestRecord(@Query("score") int score,
                                            @Query("testId") int testId);
    }
}
